﻿using HARTCalibrationTool.Commands.BatchCalibrationBoard;
using HARTCalibrationTool.Commands.HART;
using HARTCalibrationTool.SerialPortManager;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HARTCalibrationTool.Commands
{
    public enum CMDsChannelID : uint
    {
        eChannelNull = 0x00000000,
        eChannel1 = 0x00000001,
        eChannel2 = 0x00000002,
        eChannel3 = 0x00000004,
        eChannel4 = 0x00000008,
        eChannel5 = 0x00000010,
        eChannel6 = 0x00000020,
        eChannel7 = 0x00000040,
        eChannel8 = 0x00000080,
        eChannel9 = 0x00000100,
        eChannel10 = 0x00000200,
        eChannel11 = 0x00000400,
        eChannel12 = 0x00000800,
        eChannel13 = 0x00001000,
        eChannel14 = 0x00002000,
        eChannel15 = 0x00004000,
        eChannel16 = 0x00008000,
        eChannel17 = 0x00010000,
        eChannel18 = 0x00020000,
        eChannel19 = 0x00040000,
        eChannel20 = 0x00080000,
        eChannel21 = 0x00100000,
        eChannel22 = 0x00200000,
        eChannel23 = 0x00400000,
        eChannel24 = 0x00800000,
        eChannel25 = 0x01000000,
        eChannel26 = 0x02000000,
        eChannel27 = 0x04000000,
        eChannel28 = 0x08000000,
        eChannel29 = 0x10000000,
        eChannel30 = 0x20000000,
        eChannel31 = 0x40000000,
        eChannel32 = 0x80000000,
    }

    public enum CMDsChlID : byte
    {
        eChannelNull = 0,
        eChannel1 = 1,
        eChannel2 = 2,
        eChannel3 = 3,
        eChannel4 = 4,
        eChannel5 = 5,
        eChannel6 = 6,
        eChannel7 = 7,
        eChannel8 = 8,
        eChannel9 = 9,
        eChannel10 = 10,
        eChannel11 = 11,
        eChannel12 = 12,
        eChannel13 = 13,
        eChannel14 = 14,
        eChannel15 = 15,
        eChannel16 = 16,
        eChannel17 = 17,
        eChannel18 = 18,
        eChannel19 = 19,
        eChannel20 = 20,
        eChannel21 = 21,
        eChannel22 = 22,
        eChannel23 = 23,
        eChannel24 = 24,
        eChannel25 = 25,
        eChannel26 = 26,
        eChannel27 = 27,
        eChannel28 = 28,
        eChannel29 = 29,
        eChannel30 = 30,
        eChannel31 = 31,
        eChannel32 = 32,
    }

    public enum VerifyDataFrameStatus : byte
    {
        eError = 0x00,
        eWaiting = 0x01,
        eSuccess = 0x02,
        eCRCError = 0x03,
    }

    public abstract class CommandsBase : ICommand
    {
        private SerialPortsBase _serialPortManager;
        protected static CMDsChannelID _dev = 0;
        private string _commandName;
        private static byte _CMDsExeCnt = 0;
        public static bool bHasCMDExecuting = false;
        private static CMDsChlID _currentGroupChl;
        private static Dictionary<CMDsChlID, bool> _transducersStatus;

        public event EventHandler CommandSuccess;

        private bool _IsCMDReceived = false;

        static CommandsBase()
        {
            _transducersStatus = new Dictionary<CMDsChlID, bool>()
            {
                { CMDsChlID.eChannel1, false},
                { CMDsChlID.eChannel2, false},
                { CMDsChlID.eChannel3, false},
                { CMDsChlID.eChannel4, false},
                { CMDsChlID.eChannel5, false},
                { CMDsChlID.eChannel6, false},
                { CMDsChlID.eChannel7, false},
                { CMDsChlID.eChannel8, false},
                { CMDsChlID.eChannel9, false},
                { CMDsChlID.eChannel10, false},
                { CMDsChlID.eChannel11, false},
                { CMDsChlID.eChannel12, false},
                { CMDsChlID.eChannel13, false},
                { CMDsChlID.eChannel14, false},
                { CMDsChlID.eChannel15, false},
                { CMDsChlID.eChannel16, false},
                { CMDsChlID.eChannel17, false},
                { CMDsChlID.eChannel18, false},
                { CMDsChlID.eChannel19, false},
                { CMDsChlID.eChannel20, false},
                { CMDsChlID.eChannel21, false},
                { CMDsChlID.eChannel22, false},
                { CMDsChlID.eChannel23, false},
                { CMDsChlID.eChannel24, false},
                { CMDsChlID.eChannel25, false},
                { CMDsChlID.eChannel26, false},
                { CMDsChlID.eChannel27, false},
                { CMDsChlID.eChannel28, false},
                { CMDsChlID.eChannel29, false},
                { CMDsChlID.eChannel30, false},
                { CMDsChlID.eChannel31, false},
                { CMDsChlID.eChannel32, false},
            };
        }

        public CommandsBase(SerialPortsBase serialPortManager, string commandName)
        { 
            this._serialPortManager = serialPortManager;
            this._serialPortManager.SetCurrentCMD(this);

            this._commandName = commandName;
        }

        public CMDsChlID CurrentGroupChannel
        {
            set { _currentGroupChl = value; }
            get { return _currentGroupChl; }
        }

        public SerialPortsBase SerialPortMager
        {
            set { this._serialPortManager = value; }
            get { return this._serialPortManager; }
        }

        public string CommandName
        { 
            get { return this._commandName; }
            set { this._commandName = value; }
        }

        public void CMDsExeCntIncrement()
        {
            _CMDsExeCnt++;
        }

        public void SetCMDsExecutingStatus(bool bStatus)
        {
            bHasCMDExecuting = bStatus;
        }

        public bool GetCMDsExecutionStatus()
        { 
            return bHasCMDExecuting;
        }

        public void ClearCMDsExeCnt()
        {
            _CMDsExeCnt = 0;
        }

        public byte GetCMDExeCnt()
        { 
            return _CMDsExeCnt;
        }

        public void SetCMDsChannelID(CMDsChannelID chl)
        { 
            _dev = chl;
        }

        public CMDsChannelID GetCMDsChannelID()
        {
            return _dev;
        }

        public void PrintMessage(string msg)
        {
            SerialPortsBase.PrintMessage(msg);
        }

        public abstract Task ExecuteCMD();
        public abstract Task ParseResponse(byte[] data);
        public abstract VerifyDataFrameStatus VerifyDataFrameIntegrity(byte[] data);
        public abstract void OnTimeout();
        public abstract void OnSuccess();
        public abstract void OnFailure();

        public static void SetTransducersStatus(bool bStatus)
        {
            _transducersStatus[_currentGroupChl] = bStatus;
        }

        public static void ClearTransducersStatus()
        {
            foreach (var key in _transducersStatus.Keys.ToList())
            {
                _transducersStatus[key] = false;
            }
        }

        public static bool GetTransducerStatus(CMDsChlID chl)
        {
            return _transducersStatus[chl];
        }

        public static bool bHasTransducersOnline()
        {
            bool result = false;

            foreach (var key in _transducersStatus.Keys.ToList())
            {
                result |= _transducersStatus[key];
            }

            return result;
        }

        public void CommandExeSuccess()
        {
            CommandSuccess?.Invoke(this, EventArgs.Empty);
        }

        public void SetCurrentCMDResponseFinishedFlg()
        { 
            _IsCMDReceived = true;
        }

        public void ClrCurrentCMDResponseFinishedFlg()
        {
            _IsCMDReceived = false;
        }

        public bool IsCurrentCMDResponseFinished()
        { 
            return _IsCMDReceived;
        }
    }
}
